package com.xbx.baseweb.service.impl;


import com.xbx.baseweb.entity.email.EmailAttach;
import com.xbx.baseweb.entity.email.EmailParam;
import com.xbx.baseweb.entity.email.EmailSendResult;
import com.xbx.baseweb.service.EmailService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.*;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * 邮件发送服务 使用thymeleaf进行邮件模板渲染
 */
@Slf4j
@Service
public class EmailServiceImpl implements EmailService {

    private static Map<String, String> templateRepository = new HashMap<>(4);

    @Autowired
    private TemplateEngine templateEngine;

    @Autowired
    private JavaMailSender mailSender;

    @Value("${xbx.email.from}")
    private String emailFrom;

    private String getTemplateByName(String templateName) {
        String template = templateRepository.get(templateName);
        if (StringUtils.isBlank(template)) {
            try {
                InputStream stream = this.getClass().getClassLoader().getResourceAsStream("templates/" + templateName + ".html");
                byte[] temp = new byte[2048];
                IOUtils.read(stream, temp);
                template = new String(temp, "UTF-8");
                templateRepository.put(templateName, template);
            } catch (FileNotFoundException e) {
                throw new RuntimeException("邮件服务:发送邮件失败;路径中找不到邮件模板;templateName="+templateName);
            } catch (IOException e) {
                throw new RuntimeException("邮件服务:发送邮件失败;获取模板内容时发生异常;templateName="+templateName);
            }
        }
        return template;
    }


    @Override
    public EmailSendResult send(EmailParam param, String templateName) {
        if (param == null) {
            return EmailSendResult.build(-101,"邮件服务:邮件参数为空");
        }

        if (StringUtils.isBlank(param.getSubject())) {
            return EmailSendResult.build(-103,"邮件服务:邮件主题不能为空");
        }

        if (CollectionUtils.isEmpty(param.getSendTo())) {
            return EmailSendResult.build(-104,"邮件服务:邮件接收者不能为空");
        }

        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper;

        try {
            helper = new MimeMessageHelper(message, true, "UTF-8");
            helper.setFrom(emailFrom);
            helper.setSubject(param.getSubject());
            if (StringUtils.isNotBlank(templateName)) {
                Context context = new Context(Locale.CHINESE, param.getModel());
                String html = templateEngine.process(templateName, context);
                helper.setText(html, true);
            }
        } catch (MessagingException e) {
            log.info("邮件服务:发送邮件发生异常;", e);
            return EmailSendResult.build(-201,"构造邮件内容时发生异常");
        }
        for (EmailAttach attachment : param.getAttaches()) {
            if (attachment != null) {
                InputStreamSource inputStreamSource = new ByteArrayResource(attachment.getFile());
                try {
                    helper.addAttachment(attachment.getFileName(),inputStreamSource);
                } catch (MessagingException e) {
                    log.info("邮件服务:发送邮件发生异常;添加附件时发生异常;fileName={}",attachment.getFileName(), e);
                    return EmailSendResult.build(-105, "邮件发送发生异常;附件名:" + attachment.getFileName());
                }
            }
        }
        for (String to : param.getSendTo()) {
            try {
                helper.setTo(to);
            } catch (MessagingException e) {
                log.info("邮件服务:发送邮件异常;to={}",to,e);
                return EmailSendResult.build(-201,"发送邮件发送异常");
            }
            mailSender.send(message);
        }
        log.info("邮件发送成功;to:{},map={},attachSize={}", param.getSendTo(), param.getModel(), param.getAttaches().size());
        return EmailSendResult.build(0, "success");
    }

    @Override
    public void clearCache() {
        templateEngine.clearTemplateCache();
    }
}
